package cn.amossun.starter.common.crypto.rule;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.amossun.starter.common.enums.OutTypeEnum;
import cn.amossun.starter.common.properties.DataSecurityProperties;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Logger;

/**
 * 加密规则
 */
public class EncryptRule extends AbstractRule {

    private static Logger log = Logger.getLogger(EncryptRule.class.toString());

    public EncryptRule(DataSecurityProperties properties) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, UnsupportedEncodingException {
        setCharacterSet(Charset.forName(properties.getCharacterName()));
        setOutType(OutTypeEnum.valueOf(properties.getOutType().toUpperCase()));
        setProperties(properties);
        setOpmode(Cipher.ENCRYPT_MODE);
        //setCipher(buildCipher());
    }

    public String base64EncryptValue(String originalValue) throws BadPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, UnsupportedEncodingException {
        if(StrUtil.isEmpty(originalValue)) {
            return originalValue;
        }
        byte[] encrypted = buildCipher().doFinal(originalValue.getBytes(getCharacterSet()));
        return Base64Encoder.encode(encrypted);
    }

    public String encodeEncryptValue(String originalValue) throws BadPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, UnsupportedEncodingException {
        if(StrUtil.isEmpty(originalValue)) {
            return originalValue;
        }
        //设置前后缀特殊字符时,避免重复加密.
        if(decryptConfigExists() && isDecryptData(originalValue)) {
            return originalValue;
        }

        byte[] encrypted = buildCipher().doFinal(originalValue.getBytes(getCharacterSet()));
        if(getOutType() == OutTypeEnum.BASE64) {
            return appendDataSuffix(Base64Encoder.encode(encrypted));
        }

        if(getOutType() == OutTypeEnum.HEX) {
            return appendDataSuffix(HexUtil.encodeHexStr(encrypted));
        }
        return originalValue;
    }

    protected String appendDataSuffix(String encryptData) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(StrUtil.isNotEmpty(getProperties().getDataBeforeSuffix()) ? getProperties().getDataBeforeSuffix() :StrUtil.EMPTY);
        stringBuilder.append(encryptData);
        stringBuilder.append(StrUtil.isNotEmpty(getProperties().getDataAfterSuffix()) ? getProperties().getDataAfterSuffix() :StrUtil.EMPTY);
        return stringBuilder.toString();
    }

}
